package it.traveldreamWeb.customer;

import it.traveldream.beans.PackageManagerInterface;
import it.traveldream.dto.ExcursionDTO;
import it.traveldream.dto.HotelDTO;
import it.traveldream.dto.HotelDTO.HotelRoomType;
import it.traveldream.dto.TPDTO;
import it.traveldream.exceptions.TPNotFoundException;
import it.traveldreamWeb.shared.ExcursionDataModel;
import it.traveldreamWeb.shared.HotelDataModel;
import it.traveldreamWeb.shared.HotelRoom;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import org.primefaces.event.SelectEvent;

@ManagedBean(name="packageCustomizationBean")
@ViewScoped
public class PackageCustomizationBean {

	private Long TPId;
	private TPDTO selectedTP;
	private List<HotelDTO> availableHotels = new ArrayList<>();
	private List<ExcursionDTO> availableExs = new ArrayList<>();
	private ExcursionDataModel exsDataModel;
	private HotelDataModel hotelDataModel;
	
	private HotelDTO selectedHotel;
	private List<HotelRoom> selectedRooms = new ArrayList<>();
	private ExcursionDTO selectedEx;
	private ExcursionDTO[] selectedExs;
	
	
	private String error;
	
	@EJB
	private PackageManagerInterface packageManager;
	
	@ManagedProperty(value="#{reservationBean}")
	private ReservationBean session;

	
	public void init(){
		// clean session
		this.session.setSelectedHotel(null);
		this.session.setSelectedExs(null);
		this.session.setSelectedRooms(null);
				
		if (this.TPId == null){
			ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
			try {
				String path = context.getRequestContextPath()+context.getRequestServletPath();
				context.redirect(path.replace("PackageView.xhtml", "PackageList.xhtml"));
			} catch (IOException e) {
				throw new RuntimeException();
			}
		} else {
			this.selectedTP = new TPDTO();
			try {
				this.selectedTP.setTPId(this.TPId);
				
				this.selectedTP = this.packageManager.getTP(this.selectedTP);
				this.selectedHotel = this.selectedTP.getHotel();
				this.selectedExs = new ExcursionDTO[this.selectedTP.getExcursions().size()];
				this.selectedExs = this.selectedTP.getExcursions().toArray(this.selectedExs);
				
				// inizializzo le stanze a 0
				for (Map.Entry<HotelRoomType, Integer> e : this.selectedHotel.getRooms().entrySet()){
					HotelRoom r = new HotelRoom();
					r.setType(e.getKey());
					r.setTotalRooms(this.selectedHotel.getRooms().get(e.getKey()));
					r.setPrice(this.selectedHotel.getPrices().get(e.getKey()));
					r.setSelectedRooms(0);
					this.selectedRooms.add(r);
				}
				
				this.availableHotels = this.packageManager.getAlternativeHotels(this.selectedTP);
				this.availableHotels.add(this.selectedHotel);
				this.hotelDataModel = new HotelDataModel(this.availableHotels);
				
				this.availableExs = this.packageManager.getAlternativeExcursions(this.selectedTP);
				this.availableExs.addAll(Arrays.asList(this.selectedExs));
				this.exsDataModel = new ExcursionDataModel(this.availableExs);
			} catch (TPNotFoundException e) {
				this.setError("Invalid request. Please use links from inside the site");
			} catch (Exception e) {
				this.setError("Internal error. Please go back and try again");
			}
		}
	}
	
	public String customize(){
		this.setError("");
		try{
			boolean someRoom = false;
			for (HotelRoom h : this.selectedRooms)
				if (h.getSelectedRooms() != null && h.getSelectedRooms() > 0){
					someRoom = true;
					break;
				}	
			if (! someRoom){
				this.setError("Please, choose some room first");
				return "";
			}
			
			this.session.setSelectedHotel(this.selectedHotel);
			this.session.setSelectedExs(Arrays.asList(this.selectedExs));
			this.session.setSelectedRooms(this.selectedRooms);
			return "ReservationSummary?faces-redirect=true";
		} catch (Exception e){
			this.setError("Internal error. Please try again");
			return null;
		}
	}
	
	public Long getTPId() {
		return this.TPId;
	}

	public void setTPId(Long tPId) {
		this.TPId = tPId;
	}

	public ReservationBean getSession() {
		return this.session;
	}

	public void setSession(ReservationBean session) {
		this.session = session;
	}

	public ExcursionDataModel getExsDataModel() {
		return this.exsDataModel;
	}

	public HotelDataModel getHotelDataModel() {
		return this.hotelDataModel;
	}

	public List<HotelDTO> getAvailableHotels() {
		return this.availableHotels;
	}

	public void setAvailableHotels(List<HotelDTO> availableHotels) {
		this.availableHotels = availableHotels;
	}

	public List<ExcursionDTO> getAvailableExs() {
		return this.availableExs;
	}

	public void setAvailableExs(List<ExcursionDTO> availableExs) {
		this.availableExs = availableExs;
	}

	public HotelDTO getSelectedHotel() {
		return this.selectedHotel;
	}

	public void setSelectedHotel(HotelDTO selectedHotel) {
		this.selectedHotel = selectedHotel;
	}
	
	public List<HotelRoom> getRoomsAsList(HotelDTO hotel){
		if (hotel != null){
			List<HotelRoom> list = new ArrayList<>();
			HotelRoom current;
			for (HotelRoomType type : hotel.getRooms().keySet()){
				current = new HotelRoom();

				current.setTotalRooms(hotel.getRooms().get(type));
				current.setPrice(hotel.getPrices().get(type));
				current.setType(type);
				current.setSelectedRooms(0);
				list.add(current);
			}
			return list;
		} 
		return null;
	}

	public ExcursionDTO[] getSelectedExs() {
		return this.selectedExs;
	}

	public void setSelectedExs(ExcursionDTO[] selectedExs) {
		this.selectedExs = selectedExs;
	}

	public ExcursionDTO getSelectedEx() {
		return this.selectedEx;
	}

	public void setSelectedEx(ExcursionDTO selectedEx) {
		this.selectedEx = selectedEx;
	}

	public List<HotelRoom> getSelectedRooms() {
		return this.selectedRooms;
	}

	public void setSelectedRooms(List<HotelRoom> selectedRooms) {
		this.selectedRooms = selectedRooms;
	}

	public String getError() {
		return this.error;
	}

	public void setError(String error) {
		this.error = error;
	}
	
	public void onHotelSelect(SelectEvent event) {  
        HotelDTO hotel = ((HotelDTO) event.getObject());  
  
        this.selectedRooms = new ArrayList<>();
        // inizializzo le stanze a 0
		for (Map.Entry<HotelRoomType, Integer> e : hotel.getRooms().entrySet()){
			HotelRoom r = new HotelRoom();
			r.setType(e.getKey());
			r.setTotalRooms(hotel.getRooms().get(e.getKey()));
			r.setPrice(hotel.getPrices().get(e.getKey()));
			r.setSelectedRooms(0);
			this.selectedRooms.add(r);
		}
    }

}
